home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / bprof-1.1 / bprof-1 / bprof / bmon.c next >
Encoding:
C/C++ Source or Header  |  1994-07-13  |  3.0 KB  |  124 lines

  1. /* Routines with the same name as in gmon, to make compilation easier
  2.    for the user, who only has to specify -pg when linking.  The
  3.    drawback is that it is a lot less portable than having the user
  4.    call a hypothetical bmon() routine at the start of their program,
  5.    which would then use atexit(_mcleanup). */
  6.  
  7. #include <sys/time.h>
  8. #include <signal.h>
  9. #include <unistd.h>
  10. #include <fcntl.h>
  11. #include <stdlib.h>
  12. #include <memory.h>
  13. #include <stdio.h>
  14.  
  15. /* sigcontext copied from linux/kernel/signal.c
  16.    Why is this not in any linux/.h file? */
  17.  
  18. struct sigcontext_struct {
  19.     unsigned short gs, __gsh;
  20.     unsigned short fs, __fsh;
  21.     unsigned short es, __esh;
  22.     unsigned short ds, __dsh;
  23.     unsigned long edi;
  24.     unsigned long esi;
  25.     unsigned long ebp;
  26.     unsigned long esp;
  27.     unsigned long ebx;
  28.     unsigned long edx;
  29.     unsigned long ecx;
  30.     unsigned long eax;
  31.     unsigned long trapno;
  32.     unsigned long err;
  33.     unsigned long eip;
  34.     unsigned short cs, __csh;
  35.     unsigned long eflags;
  36.     unsigned long esp_at_signal;
  37.     unsigned short ss, __ssh;
  38.     unsigned long i387;
  39.     unsigned long oldmask;
  40.     unsigned long cr2;
  41. };
  42.  
  43. /* I should have used the profil() routine to ease porting, but it
  44.    cannot use a finer scale than one counter per two bytes. */
  45.  
  46. static unsigned long lowpc, highpc;
  47. static unsigned int *bbuf;
  48. static unsigned long bbufsize;
  49.  
  50. static void profhandler(int signr, struct sigcontext_struct sigcon)
  51. {
  52.     unsigned long index = sigcon.eip - lowpc;
  53.     if (index < bbufsize)
  54.     bbuf[index]++;
  55. }    
  56.  
  57. void monstartup(unsigned long low, unsigned long high)
  58. {
  59.     struct sigaction sigact;
  60.     struct itimerval value;
  61.     sigset_t sigset;
  62.  
  63.     lowpc = low;
  64.     highpc = high;
  65.     bbufsize = high - low;
  66.     bbuf = sbrk(bbufsize * sizeof(*bbuf));
  67.     if (bbuf == (typeof(bbuf))-1) {
  68.     perror("monstartup");
  69.     exit(1);
  70.     }
  71.     /* sbrk-ed memory is supposed to be zero, but I've seen otherwise */
  72.     memset(bbuf, 0, bbufsize * sizeof(*bbuf));
  73.    
  74.     sigact.sa_handler = (void (*)(int))profhandler;
  75.     sigemptyset(&sigset);
  76.     sigact.sa_mask = sigset;
  77.     sigact.sa_flags = SA_RESTART;
  78.  
  79.     value.it_interval.tv_sec = 0;
  80.     value.it_interval.tv_usec = 1; /* Gets rounded up to 1e6/HZ */
  81.     value.it_value.tv_sec = 0;
  82.     value.it_value.tv_usec = 1;
  83.  
  84.     sigaction(SIGVTALRM, &sigact, 0);
  85.     setitimer(ITIMER_VIRTUAL, &value, 0);
  86. }
  87.  
  88. void _mcleanup(void)
  89. {
  90.     int fd;
  91.     const char *dir;
  92.     unsigned long i;
  93.  
  94.     if ((dir = getenv("BPROFDIR"))) {
  95.     if (chdir(dir)) {
  96.         perror("mcleanup: could not chdir to BPROFDIR");
  97.         return;
  98.     }
  99.     }
  100.  
  101.     fd = creat("bmon.out", 0666);
  102.     if (fd == -1) {
  103.     perror("mcleanup: bmon.out");
  104.     return;
  105.     }
  106.  
  107.     for (i = 0; i < bbufsize; i++) {
  108.     if (bbuf[i]) {
  109.         unsigned long pc = lowpc + i;
  110.         if (write(fd, &pc, sizeof(pc)) != sizeof(pc) ||
  111.         write(fd, bbuf + i, sizeof(*bbuf)) != sizeof(*bbuf)) {
  112.         fprintf(stderr, "Error writing bmon.out\n");
  113.         return;
  114.         }
  115.     }
  116.     }
  117.     close(fd);
  118. }
  119.  
  120. void mcount(void)
  121. {
  122.     /* Do nothing to save overhead of mcount() from libgmon */
  123. }
  124.